// models/user_zdy.go
// 自定义数据类型模型定义文件
// 该文件实现了两种不同的JSON数据序列化方式：
// 1. 自定义实现sql.Scanner和driver.Valuer接口的方式
// 2. GORM内置的serializer:json序列化方式
package models

import (
	"database/sql/driver" // 数据库驱动接口包，用于实现自定义类型转换
	"encoding/json"      // JSON编解码包，用于处理JSON数据
	"errors"             // 错误处理包，用于创建自定义错误
	"fmt"                // 格式化包，用于格式化错误信息
)

// UserInfo 自定义JSON数据类型结构体
// 该结构体实现了自定义的JSON序列化和反序列化逻辑
// 通过实现sql.Scanner和driver.Valuer接口实现与数据库的交互
// 用于存储用户的兴趣爱好信息
type UserInfo struct {
	Likes []string `json:"likes"` // 用户的兴趣爱好列表，JSON序列化时的字段名为"likes"
}

// Scan 实现 sql.Scanner 接口，将数据库中的值扫描到UserInfo类型
// 参数：
//   value - 数据库中存储的原始值，通常是[]byte类型的JSON数据
// 返回值：
//   error - 扫描过程中可能发生的错误，如类型断言失败或JSON解析失败
func (j *UserInfo) Scan(value interface{}) error {
	// 将数据库值断言为[]byte类型
	bytes, ok := value.([]byte)
	if !ok {
		// 如果类型断言失败，返回格式化的错误信息
		return errors.New(fmt.Sprintf("Failed to unmarshal JSONB value:", value))
	}

	// 创建一个新的UserInfo实例用于存储解析结果
	result := UserInfo{}
	// 将[]byte数据解析为UserInfo结构体
	err := json.Unmarshal(bytes, &result)
	// 将解析结果赋值给调用者
	*j = result
	// 返回可能的解析错误
	return err
}

// Value 实现 driver.Valuer 接口，将UserInfo类型转换为数据库可存储的值
// 返回值：
//   driver.Value - 转换后的数据库值，通常是[]byte类型的JSON数据
//   error - 转换过程中可能发生的错误，如JSON序列化失败
func (j UserInfo) Value() (driver.Value, error) {
	// 将UserInfo结构体序列化为JSON字节数组
	return json.Marshal(j)
}

// Card 另一个自定义JSON数据类型结构体
// 与UserInfo不同，该结构体不实现自定义的序列化接口
// 而是依赖GORM的serializer:json标签来处理序列化
type Card struct {
	Cars []string `json:"cars"` // 用户的车辆列表，JSON序列化时的字段名为"cars"
}

// UserZdy 主模型结构体，演示两种不同的JSON序列化方式
// 该结构体包含了两种不同的JSON数据字段，分别使用不同的序列化策略
type UserZdy struct {
	ID   uint      // 主键字段，GORM会自动映射为自增主键
	Name string    `gorm:"size:32"` // 用户名称，限制长度为32个字符
	// Info字段使用自定义的序列化方式，通过实现sql.Scanner和driver.Valuer接口
	// 数据库类型为LongText，适合存储较大的文本数据
	Info UserInfo  `gorm:"type:LongText" json:"info"`
	// Card字段使用GORM内置的JSON序列化器
	// 通过serializer:json标签指定使用JSON序列化
	Card Card      `gorm:"type:longtext;serializer:json" json:"card"`
}
